//
// Created by chenxp on 2025/8/27.
//
#include "AppConfig.h"
#include "utils.h"
#include <iostream>
#include <fstream>
#include <stdexcept>

AppConfig* AppConfig::instance = nullptr;

AppConfig::AppConfig() = default;

AppConfig::~AppConfig() {
    if (instance != nullptr) {
        delete instance;
        // 避免野指针
        instance = nullptr;
    }
}

static std::mutex lock_init_instance;

AppConfig* AppConfig::getInstance() {
    if (instance == nullptr) {
        // 加锁: 确保只有一个线程可以进入
        lock_init_instance.lock();
        if (instance == nullptr) {
            instance = new AppConfig();
        }
        // 解锁
        lock_init_instance.unlock();
    }
    return instance;
}

void AppConfig::loadFileConfig(const std::string &filePath) {
    // RAII（资源获取即初始化）机制, 自动加锁。函数结束、return、抛出异常等会自动释放锁。
    std::lock_guard lock(mu_);
    std::cout << "Loading file config from: " << filePath << std::endl;
    std::ifstream fin(filePath);
    if (!fin.is_open()) {
        throw std::runtime_error("Open config failed: " + filePath);
    }
    std::string line;
    while (std::getline(fin, line)) {
        if (line.empty() || line[0] == '#') continue;
        auto pos = line.find('=');
        if (pos == std::string::npos) continue;
        auto key = StringUtils::trim(line.substr(0, pos));
        auto val = StringUtils::trim(line.substr(pos + 1));
        // 添加到键值对
        if (!key.empty()) kv_[key] = val;
    }
}

std::string AppConfig::getString(const std::string &key, const std::string& def) const {
    // 返回一个迭代器 it, 指向键值对中的key
    auto it = kv_.find(key);
    // kv_.end()表示map的末尾（无效位置）,说明键不存在
    if (it == kv_.end()) return def;
    // 如果键存在，it指向对应的键值对
    // it->first是键（key），it->second是值（value）。
    return it->second;
}

int AppConfig::getInt(const std::string &key, int def) const {
    auto val = getString(key);
    if (val.empty()) return def;
    // 避免转换错误
    try { return std::stoi(val); }
    catch (...) { return def; }
}

bool AppConfig::contains(const std::string& key) const {
    // return kv_.find(key) != kv_.end();
    return kv_.count(key) > 0;
}

